package com.adaptiveAgingAdmin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.adaptiveAgingAdmin.code.Code;
import com.adaptiveAgingAdmin.domain.Admin;
import com.adaptiveAgingAdmin.domain.Menu;
import com.adaptiveAgingAdmin.domain.Role;
import com.adaptiveAgingAdmin.exception.NotLoginException;
import com.adaptiveAgingAdmin.mapper.AdminMapper;
import com.adaptiveAgingAdmin.service.PublicService;
import com.adaptiveAgingAdmin.utils.GsonUtil;
import com.adaptiveAgingAdmin.utils.JwtUtil;
import com.adaptiveAgingAdmin.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class PublicServiceImpl implements PublicService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private AdminMapper adminMapper;

    @Override
    public Map<String,Object> checkLogin(String username, String password) {
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(username,password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(ObjectUtil.isNull(authenticate)){
            return null;
        }
        Admin admin =(Admin) authenticate.getPrincipal();
        //更新登陆时间
        admin.setLoginTime(new Date(System.currentTimeMillis()));
        adminMapper.updateById(admin);
        List<Menu> menus= admin.getRoles().stream().map(Role::getMenus).flatMap(List::stream).distinct().collect(Collectors.toList());
        admin.setMenus(menus);
        return createToken(admin);
    }

    @Override
    public Map refreshToken(String refreshToken){
        Long adminId = JwtUtil.parseToken(refreshToken);
        String key=RedisUtil.ID_PREFIX+adminId;
        String token = RedisUtil.getHashValue(key,"refreshToken");
        if(!refreshToken.equals(token)){
            throw new NotLoginException();
        }
        String adminJson=RedisUtil.getHashValue(key,"admin");
        Admin admin=GsonUtil.parseJson(adminJson,Admin.class);
        if(ObjectUtil.isNull(admin)){
            throw new RuntimeException("无法解析用户!");
        }
        return createToken(admin);
    }

    @Override
    public Map<String, Object> heartBeat(Long id) {
        String key=RedisUtil.ID_PREFIX+id;
        if(!RedisUtil.hasKey(key)){
            throw new NotLoginException();
        }
        Map<String,Object> logout=RedisUtil.getHashValue(key,"logout");
        if(!ObjectUtil.isNull(logout)){
            return logout;
        }
        Boolean expire = RedisUtil.expire(key, Code.REDIS_KEEP_LOGIN_TIME);
        if(expire){
            return null;
        }
        throw new RuntimeException("登录状态延续失败!");
    }

    public Map<String,Object> createToken(Admin admin){
        Long adminId=admin.getId();
        String refreshToken = JwtUtil.getRefreshToken(adminId);
        String accessToken = JwtUtil.getAccessToken(adminId);
        Map<String,Object> token=new HashMap<>();
        token.put("accessToken",accessToken);
        token.put("refreshToken",refreshToken);
        token.put("admin",GsonUtil.objectToJson(admin));
        RedisUtil.setHashMap(RedisUtil.ID_PREFIX+adminId,token,Code.REDIS_KEEP_LOGIN_TIME);
        Map<String,Object> data=new HashMap();
        data.put("accessToken",accessToken);
        data.put("refreshToken",refreshToken);
        return data;
    }
}
